#include <stdio.h>
#include <stack>
#include <stack>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <math.h>

#include <stdlib.h>
#include <string.h>
//https://mp.weixin.qq.com/s/48jMBVVEqQp3IR6NpUy2QA

using namespace cv;
using namespace std;

typedef unsigned char U_CHAR;

bool Img_toGray_to3channel_toBGR(const char *inputname_char, int img_length, const char *outname);
bool Img_toGray_to3channel_toJPG(const char *inputname_char, int img_length, const char *bgrname, const char *jpgname);
vector<string> Split_by_point_and_slash(string strTime);

//#define task1 // 根据txt，找到对应的图片，灰度化，复制到3通道，生成.bgr
#ifdef task1

int main(int arg, char* argv[])
{
    bool is_success = false;

    // 生成list方式　ls frame | sed "s:^:./frame/:" >> list.txt
    ifstream fin("/home/ccc/桌面/label0619.txt"); // 图片名字列表
    string inputname_str, tmp_str;
    string input_image_name, output_image_name;

    int count_pic_num = 0;

    while (getline(fin, inputname_str))
    {
        int str_ith = 0; // string中，按照空格划分，第i个字符串

        istringstream str_stream(inputname_str); // 将list.txt中的每一行作为一个数据流
        while(str_stream >> tmp_str) // 按照空格拆分string
        {
            cout << endl << count_pic_num << "th img:" << endl;
            if(str_ith == 0)
            {
                input_image_name = "/home/ccc/桌面/image/" + tmp_str;

                cout << "image name:  " << input_image_name << endl;

                vector<string> split_str;
                split_str = Split_by_point_and_slash(input_image_name);
                output_image_name = split_str[5];

//                // 打印分割后的字符串
//                for(int ii=0; ii<split_str.size(); ii++)
//                {
//                    cout << ii << ": " << split_str[ii] << endl;
//                }
            }
            output_image_name = "/home/ccc/桌面/test/" + output_image_name + ".bgr";
            cout << "output route: " << output_image_name << endl;
            is_success = Img_toGray_to3channel_toBGR(input_image_name.c_str(), 416, output_image_name.c_str());

            break;
            str_ith ++;
        }
        if(!is_success)
        {
            cout << "transform error" << endl;
            break;
        }
        count_pic_num++;
    }
    cout << count_pic_num << " imgs have been trans" << endl;
}
#endif

//#define task2 // 根据txt，找到对应的图片，灰度化，复制到3通道，生成.jpg
#ifdef task2

int main(int arg, char* argv[])
{
    bool is_success = false;

    // 生成list方式　ls ref | sed "s:^:./mbl2_fpn/ref/:" >> list.txt
    ifstream fin("/home/ccc/桌面/label0619.txt"); // 图片名字列表
    string inputname_str, tmp_str;
    string input_image_name, output_image_name, tmp_bgr_name;

    int count_pic_num = 0;

    while (getline(fin, inputname_str))
    {
        int str_ith = 0; // string中，按照空格划分，第i个字符串

        istringstream str_stream(inputname_str); // 将list.txt中的每一行作为一个数据流
        while(str_stream >> tmp_str) // 按照空格拆分string
        {
            cout << endl << count_pic_num << "th img:" << endl;
            if(str_ith == 0)
            {
                input_image_name = "/home/ccc/桌面/image/" + tmp_str;

                cout << "image name:  " << input_image_name << endl;

                vector<string> split_str;
                split_str = Split_by_point_and_slash(input_image_name);
                output_image_name = split_str[5];

//                // 打印分割后的字符串
//                for(int ii=0; ii<split_str.size(); ii++)
//                {
//                    cout << ii << ": " << split_str[ii] << endl;
//                }
            }
            output_image_name = "/home/ccc/桌面/ruyi/" + output_image_name;
            tmp_bgr_name = output_image_name + ".bgr";
            output_image_name = output_image_name + ".jpg";

            cout << "bgr route: " << tmp_bgr_name << endl;
            cout << "output route: " << output_image_name << endl;
            is_success = Img_toGray_to3channel_toJPG(input_image_name.c_str(), 416,
                                                     tmp_bgr_name.c_str(), output_image_name.c_str());

            break;
            str_ith ++;
        }
        count_pic_num++;
        if(!is_success || count_pic_num > 50 - 1)
        {
            cout << "transform error || save full" << endl;
            break;
        }
    }
    cout << count_pic_num << " imgs have been trans" << endl;
}
#endif

// 图片 → 灰度 → 三通道 → BGR输出
// 输入图片路径、res大小，输出bgr路径
bool Img_toGray_to3channel_toBGR(const char *inputname_char, int img_length, const char *outname)
{
    CvSize sz;
    sz.height = img_length;
    sz.width = sz.height;

    // input src
    IplImage *src = 0;
    src = cvLoadImage(inputname_char, 1);

    cvShowImage("src",src);

    // resize img
    IplImage *img;
    if(src)
    {
        img = cvCreateImage(sz, src->depth, src->nChannels); // 深度U8 通道3
        cvResize(src, img, CV_INTER_CUBIC);
        cvShowImage("resize img", img);
    }
    else
    {
        cout << "not find img" << endl;
        return false;
    }

    // gray dst
    IplImage* dst = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);//用原图像指针创建新图像
    if(NULL == dst) return false;
    cvCvtColor(img, dst, CV_BGR2GRAY); // 转换颜色空间
    cvShowImage("gray", dst);

    if(cvWaitKey(10) == 0) return false;

    if (img == 0) {
        printf("Load image error\n");
        return false;
    }

    // transform
    U_CHAR *data = (U_CHAR*)dst->imageData;
    int step = dst->widthStep; // 图片一行里的 bytes(8bit) 大小，包括所有通道，一般3xwidth bytes
    printf("widthStep:%d, channel:%d, height: %d, width: %d\n", step, dst->nChannels, dst->height, dst->width);
    FILE *fp = fopen(outname, "wb");

    // bgr
    for (int cc=0; cc<3; cc++) {
        for (int hh=0; hh<dst->height; hh++) {
            for(int ww=0; ww<dst->width; ww++) {
                // mg->widthStep为图片一行里的 bytes(8bit) 大小，包括所有通道，一般3xwidth bytes
                fwrite(&data[hh*dst->widthStep + ww*dst->nChannels], sizeof(U_CHAR), 1, fp);

            }        }
    }
    cvReleaseImage(&src);
    cvReleaseImage(&img);
    cvReleaseImage(&dst);
    fclose(fp);
    return true;

    // 网络只能输入bgr格式的数据流？(因为是按照bgr训练的？yuv格式是否有转换？)
    // jpg读取后，数据存放在 imageData 里
    // imageData格式：读取每个像素点里不同通道的值，再依次读完所有像素点
    // bgr格式：先在b通道里顺序读取所有像素的数据，再继续读取g和r通道的，每像素通道8bit
    // yvu422(YCbCr422)：先存所有Y，再存v和u，v在前u在后
}

// 图片 → 灰度 → 三通道 → JPG输出
// 输入图片路径、res大小，输出jpg路径
bool Img_toGray_to3channel_toJPG(const char *inputname_char, int img_length, const char *bgrname, const char *jpgname)
{
    CvSize sz;
    sz.height = img_length;
    sz.width = sz.height;

    // input src
    IplImage *src = 0;
    src = cvLoadImage(inputname_char, 1);

    cvShowImage("src",src);

    // resize img
    IplImage *img;
    if(src)
    {
        img = cvCreateImage(sz, src->depth, src->nChannels); // 深度U8 通道3
        cvResize(src, img, CV_INTER_CUBIC);
        cvShowImage("resize img", img);
    }
    else
    {
        cout << "not find img" << endl;
        return false;
    }

    // gray img
    IplImage* gray_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);//用原图像指针创建新图像
    if(NULL == gray_img) return false;
    cvCvtColor(img, gray_img, CV_BGR2GRAY); // 转换颜色空间
    cvShowImage("gray", gray_img);

    if(cvWaitKey(10) == 0) return false;

    if (img == 0) {
        printf("Load image error\n");
        return false;
    }

    // trans img
    IplImage* trans_img = cvCreateImage(cvGetSize(gray_img), IPL_DEPTH_8U, 3);//用原图像指针创建新图像
    U_CHAR *data_trans = (U_CHAR*)trans_img->imageData;
    U_CHAR *data_gray = (U_CHAR*)gray_img->imageData;

    // 图片存储 [h w c]
    printf("widthStep:%d, channel:%d, height: %d, width: %d\n", trans_img->widthStep, trans_img->nChannels,
           trans_img->height, trans_img->width);

    // trans proc
    for (int cc=0; cc<trans_img->nChannels; cc++)
    {
        for (int hh=0; hh<trans_img->height; hh++)
        {
            for(int ww=0; ww<trans_img->width; ww++)
            {
                // mg->widthStep为图片一行里的 bytes(8bit) 大小，包括所有通道，一般3xwidth bytes
                data_trans[hh * trans_img->widthStep + ww * trans_img->nChannels + cc] =
                        data_gray[hh * gray_img->widthStep + ww * gray_img->nChannels];
            }
        }
    }

    Mat tmp_mat;
    tmp_mat = cvarrToMat(trans_img);
    Mat dst_mat = tmp_mat.clone();
    imshow("jpg", dst_mat);
    if(waitKey(10) == 27) return false;

    imwrite(jpgname, dst_mat);

    cvReleaseImage(&src);
    cvReleaseImage(&img);
    cvReleaseImage(&gray_img);
    cvReleaseImage(&trans_img);


    return true;

    // 网络只能输入bgr格式的数据流？(因为是按照bgr训练的？yuv格式是否有转换？)
    // jpg读取后，数据存放在 imageData 里
    // imageData格式：读取每个像素点里不同通道的值，再依次读完所有像素点
    // bgr格式：先在b通道里顺序读取所有像素的数据，再继续读取g和r通道的，每像素通道8bit
    // yvu422(YCbCr422)：先存所有Y，再存v和u，v在前u在后
}

// 将字符串按照 . 和 / 个字符分开
vector<string> Split_by_point_and_slash(string strTime)
{
    vector<string> result;
    string temp("");
    strTime += '/';//字符串结束标记，方便将最后一个单词入vector
    for(size_t i = 0; i < strTime.size(); i++)
    {
        if(strTime[i] == '/' || strTime[i] == '.')
        {
            result.push_back(temp);
            temp = "";
        }
        else
        {
            temp += strTime[i];
        }
    }
    return result;
}

#define list_to_bgr
#ifdef list_to_bgr
// 将list里的图片 转成bgr
int main(int arg, char* argv[]) {


    CvSize sz;
    sz.height = 608;
    sz.width = sz.height;


    // 生成list方式　ls frame | sed "s:^:./frame/:" >> list.txt

    system("mkdir ./image");
    ifstream fin("list.txt"); // 图片名字列表
    string inputname_string;

int ii = 0;
    while (getline(fin,inputname_string))
    {
        const char *inputname_char = (const char *)inputname_string.data();
        cout << "inputname_string:" << inputname_string << endl;

        string input_first_name = inputname_string.substr(0, inputname_string.rfind("."));
        input_first_name = input_first_name.erase(0,7);
        input_first_name = "./image" + input_first_name + ".bgr";
        cout << "input_first_name:" << input_first_name << endl;

        const char *outname = input_first_name.data();

        // src
        IplImage *src = 0;
        src = cvLoadImage(inputname_char, 1);

        cvShowImage("src",src);
//        cvWaitKey(0);

        // resize
        IplImage *img;
        if(src)
        {
            img = cvCreateImage(sz,src->depth,src->nChannels);
            cvResize(src,img,CV_INTER_CUBIC);
            cvShowImage("img",img);
            cvWaitKey(10);
        }

        if (img == 0) {
            printf("Load image error\n");
            return -1;
        }

        // transform
        U_CHAR *data = (U_CHAR*)img->imageData;
        int step = img->widthStep; // 图片一行里的 bytes(8bit) 大小，包括所有通道，一般3xwidth bytes
        printf("widthStep:%d, height: %d, width: %d\n",step, img->height, img->width);
        FILE *fp = fopen(outname, "wb");

        // bgr
        for (int cc=0; cc<img->nChannels; cc++) {
            for (int hh=0; hh<img->height; hh++) {
                for(int ww=0; ww<img->width; ww++) {
                    // mg->widthStep为图片一行里的 bytes(8bit) 大小，包括所有通道，一般3xwidth bytes
                    fwrite(&data[hh*img->widthStep + ww*img->nChannels + cc], sizeof(U_CHAR), 1, fp);
                }
            }
        }
        fclose(fp);

        // 网络只能输入bgr格式的数据流？(因为是按照bgr训练的？yuv格式是否有转换？)
        // jpg读取后，数据存放在 imageData 里
        // imageData格式：读取每个像素点里不同通道的值，再依次读完所有像素点
        // bgr格式：先在b通道里顺序读取所有像素的数据，再继续读取g和r通道的，每像素通道8bit
        // yvu422(YCbCr422)：先存所有Y，再存v和u，v在前u在后

        ii ++;
        if (ii > 5000) break;
    }


    return 0;
}
#endif


//#define save_image_to_dif_pos // 用于将图片分类到不同目录下 分类网络需要
#ifdef save_image_to_dif_pos

vector<string> MY_split(string strTime);
bool Image_To_Single_Channal_BGR(const char *inputname_char, int length, const char *outname);
bool Image_To_JPG(const char *inputname_char, int length, const char *outname);

// 将图片按照list里的类别，放于不同文件夹
int main(int arg, char* argv[])
{
    bool is_success = false;
    // 创建保存路径
    {
        string str_name;
        int ith = 1;
        for(int ii=0; ii<4; ii++)
        {
            stringstream sin;
            sin << ith;
            sin >> str_name;
            str_name = "mkdir ./" + str_name;

            cout << "sys order: " << str_name << endl;

            system(str_name.c_str());

            ith++;
        }
    }

    // 生成list方式　ls frame | sed "s:^:./frame/:" >> list.txt
    ifstream fin("train_ship.txt"); // 图片名字列表
    string inputname_str, tmp_str;
    string input_image_name, output_image_name;
//    Mat src_image;
    int num_clsss[4] = {0};

    while (getline(fin, inputname_str))
    {
        int str_ith = 0; // string中，按照空格划分，第i个字符串

        istringstream str_stream(inputname_str); // 将list.txt中的每一行作为一个数据流
        while(str_stream >> tmp_str) // 按照空格拆分string
        {
            if(str_ith == 0)
            {
                input_image_name = "./ship/" + tmp_str;
//                src_image = imread(input_image_name);
//                imshow("src", src_image);
//                if(waitKey(0) == 27) break;
                cout << endl << "image name:  " << input_image_name << endl;

                vector<string> split_str;
                split_str = MY_split(input_image_name);
                output_image_name = split_str[3];

                // 打印分割后的字符串
                //for(int ii=0; ii<split_str.size(); ii++)
                //{
                //    cout << ii << ": " << split_str[ii] << endl;
                //}
            }
            else if(str_ith == 3)
            {
                istringstream iss(tmp_str);
                int class_int;
                iss >> class_int;

                switch (class_int) {
                case 1:
                    num_clsss[0]++;
                    output_image_name = "./1/" + output_image_name + ".bgr";
                    break;
                case 2:
                    num_clsss[1]++;
                    output_image_name = "./2/" + output_image_name + ".bgr";
                    break;
                case 3:
                    num_clsss[2]++;
                    output_image_name = "./3/" + output_image_name + ".bgr";
                    break;
                case 4:
                    num_clsss[3]++;
                    output_image_name = "./4/" + output_image_name + ".bgr";

                    break;
                default:
                    break;
                }
                cout << "output route: " << output_image_name << endl;
                is_success = Image_To_Single_Channal_BGR(input_image_name.c_str(), 224, output_image_name.c_str());
//                is_success = Image_To_JPG(input_image_name.c_str(), 224, output_image_name.c_str());
            }
            str_ith ++;
        }
        if(!is_success)
        {
            cout << "transform error" << endl;
            break;
        }
    }
    int total_num_image = 0;
    for(int ii=0; ii<4; ii++)
    {
        cout << "class " << ii+1 << " num: " << num_clsss[ii] << endl;
        total_num_image += num_clsss[ii];
    }
    cout << "total num: " << total_num_image << endl;
}

#endif





